package com.hlkj.baojin.service.impl;

import com.google.common.collect.Maps;
import com.hlkj.baojin.constant.BaojinConstant;
import com.hlkj.baojin.dao.IDeviceDao;
import com.hlkj.baojin.dao.IDeviceErrLogDao;
import com.hlkj.baojin.dao.repository.AlarmRecordRepository;
import com.hlkj.baojin.dao.repository.DeviceRepository;
import com.hlkj.baojin.dao.repository.EarlyAlarmRecordRepository;
import com.hlkj.baojin.entity.Device;
import com.hlkj.baojin.entity.DeviceErrLog;
import com.hlkj.baojin.entity.User;
import com.hlkj.baojin.entity.dto.*;
import com.hlkj.baojin.entity.dto.DeviceDto;
import com.hlkj.baojin.jwt.JwtUser;
import com.hlkj.baojin.service.*;
import com.hlkj.baojin.utils.ErrororUtil;
import com.hlkj.baojin.utils.MyLists;
import com.hlkj.baojin.utils.bean.CopyUtil;
import com.hlkj.baojin.utils.bean.JsonResult;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author HULIN
 * @created with: baojin
 * @package com.hlkj.baojin.service.impl
 * @description:
 * @date 2018/12/17 12:54
 * @modified By:
 * @Copyright © 2018 HAILIANG Info. Tech Ltd. All rights reserved.
 */
@Service
public class DeviceServiceImpl implements DeviceService {

    @Autowired
    private IDeviceDao deviceDao;
    @Autowired
    private DeviceRepository deviceRepository;
    @Autowired
    private AlarmRecordRepository alarmRecordRepository;
    @Autowired
    private EarlyAlarmRecordRepository earlyAlarmRecordRepository;
    @Autowired
    private CompanyService companyService;
    @Autowired
    private ICompanyAreaService companyAreaService;
    @Autowired
    private IUserService userService;
    @Autowired
    private IFileService fileService;
    @Autowired
    private IDeviceErrLogDao deviceErrLogDao;

    @Override
    public IDeviceDao getDeviceDao() {
        return this.deviceDao;
    }

    @Override
    @Transactional
    public void saveDevice(DeviceDto deviceDto) {

        JwtUser currentUser = userService.getCurrentUser();
        ErrororUtil.isFalseNull(deviceDao.findByIndexNumAndDelete(deviceDto.getIndexNum(), BaojinConstant.IS_NO_DELETE),
                "设备新增", "索引编号已使用,请更换");

        valueDetech(deviceDto);

        CompanyDto companyDto = companyService.findCompanyById(deviceDto.getBelongCompany());
        deviceDto.setBelongCompanyName(companyDto.getName());
        Device device = new Device(currentUser.getId(), System.currentTimeMillis(), 0, BaojinConstant.IS_NO_DELETE);
        BeanUtils.copyProperties(deviceDto, device, CopyUtil.getNullPropertyNames(deviceDto));
        device.setCompanyAreaName(companyAreaService.getCompanyAreaNameByCompanyAreaId(device.getCompanyArea()));
        deviceDao.save(device);
    }

    @Override
    @Transactional
    public void updateDevice(DeviceDto deviceDto) {

        ErrororUtil.isTrueNull(deviceDto.getId(), "更新设备", "更新id不存在");

        JwtUser currentUser = userService.getCurrentUser();

        valueDetech(deviceDto);

        if (MyLists.notNullAndEmpty(deviceDto.getTechManual())) {
            deviceDto.setTechManual(fileService.updateMultiFile(deviceDto.getTechManual()));
        }

        if (MyLists.notNullAndEmpty(deviceDto.getEmergencyPlan())) {
            deviceDto.setEmergencyPlan(fileService.updateMultiFile(deviceDto.getEmergencyPlan()));
        }
        ErrororUtil.isTrue(StringUtils.isBlank(deviceDto.getId()), "更新设备", "数据异常");

        Device device = deviceDao.findByIdAndDelete(deviceDto.getId(), BaojinConstant.IS_NO_DELETE);
        Device deviceTemp = deviceDao.findByIndexNumAndDelete(deviceDto.getIndexNum(), BaojinConstant.IS_NO_DELETE);

        ErrororUtil.isTrue(deviceTemp != null && !device.getId().equals(deviceTemp.getId()),
                "更新设备", "索引编号已使用,请更换");

        BeanUtils.copyProperties(deviceDto, device);
        device.setUpdateMan(currentUser.getId());
        device.setUpdateTime(System.currentTimeMillis());

        device.setCompanyAreaName(companyAreaService.getCompanyAreaNameByCompanyAreaId(device.getCompanyArea()));
        deviceDao.save(device);
    }

    @Override
    @Transactional
    public void deleteDevice(String deviceId) {
        //ErrororUtil.isError("删除设备", "存在异常的设备, 无法删除");

        Device device = deviceDao.findByIdAndDelete(deviceId, BaojinConstant.IS_NO_DELETE);
        ErrororUtil.isTrueNull(device, "删除设备", "不存在所删除设备");
        ErrororUtil.isTrue(device.getStatus().equals(1), "删除设备", "设备处于异常无法删除");

        JwtUser currentUser = userService.getCurrentUser();
        Device deviceDetele = new Device(deviceId, currentUser.getId(), System.currentTimeMillis(), BaojinConstant.IS_DELETE);
        deviceRepository.updateDeviceNotNull(deviceDetele);
        alarmRecordRepository.deleteAlarmRecord(deviceId, 1);
        earlyAlarmRecordRepository.deleteEarlyAlarmRecord(deviceId, 1);
    }

    @Override
    public JsonResult findDevice(DeviceSearchDto deviceSearchDto) {

        JwtUser currentUser = userService.getCurrentUser();
        User user = userService.getUserDao().getById(currentUser.getId());

        ModelList<Device> deviceModelList = new ModelList<>();
        if (user.getType().equals(2)) {
            deviceModelList = deviceRepository.getDevice(deviceSearchDto);
        } else if (user.getType().equals(1)) {
            deviceSearchDto.setDeptId(user.getDeptId());
            deviceModelList = deviceRepository.getDevice(deviceSearchDto);

        }
        List<Device> deviceList = deviceModelList.getList();

        List<DeviceDto> deviceDtoList = new ArrayList<>();
        for (Device device : deviceList) {
            DeviceDto deviceDto = new DeviceDto();
            deviceDto.setId(device.getId());
            deviceDto.setBelongCompanyName(companyService.getCompanyNameById(device.getBelongCompany()));
            deviceDto.setCompanyArea(device.getCompanyArea());
            deviceDto.setCompanyAreaName(companyAreaService.getCompanyAreaNameByCompanyAreaId(device.getCompanyArea()));
            deviceDto.setMonitorObject(device.getMonitorObject());
            deviceDto.setMonitorArticle(device.getMonitorArticle());
            deviceDto.setMonitorType(device.getMonitorType());
            deviceDto.setCreateTime(device.getCreateTime());
            deviceDto.setStatus(device.getStatus());
            deviceDtoList.add(deviceDto);
        }

        Map maps = Maps.newHashMap();
        maps.put("list", deviceDtoList);
        maps.put("count", deviceModelList.getCount());
        return JsonResult.success(maps);
    }

    @Override
    public DeviceDto findDeviceById(String deviceId) {

        Device device = deviceDao.findByIdAndDelete(deviceId, BaojinConstant.IS_NO_DELETE);
        DeviceDto deviceDto = new DeviceDto();
        BeanUtils.copyProperties(device, deviceDto);

        deviceDto.setTechManual(fileService.transform(device.getTechManual()));
        if (MyLists.notNullAndEmpty(deviceDto.getEmergencyPlan())) {
            deviceDto.setEmergencyPlan(fileService.transform(device.getEmergencyPlan()));
        }

        deviceDto.setCompanyAreaName(companyAreaService.getCompanyAreaNameByCompanyAreaId(device.getCompanyArea()));

        return deviceDto;
    }

    @Override
    public List<String> getIdsByNameAndItem(String search) {
        return deviceRepository.getIdsByNameAndItem(search);
    }

    @Override
    public DeviceDto findDeviceByIdAndMonitorType(String deviceId, Integer monitorType) {
        Device device = null;
        if (monitorType != null) {
            device = deviceDao.findByIdAndMonitorTypeAndDelete(deviceId, monitorType, BaojinConstant.IS_NO_DELETE);
        } else {
            device = deviceDao.findByIdAndDelete(deviceId, BaojinConstant.IS_NO_DELETE);
        }
        DeviceDto deviceDto = new DeviceDto();
        BeanUtils.copyProperties(device, deviceDto);
        deviceDto.setTechManual(fileService.transform(device.getTechManual()));
        if (MyLists.notNullAndEmpty(deviceDto.getEmergencyPlan())) {
            deviceDto.setEmergencyPlan(fileService.transform(device.getEmergencyPlan()));
        }
        return deviceDto;
    }

    @Override
    public List<Details> getError(String deviceId) {

        DeviceErrLog deviceErrLog = deviceErrLogDao.findByDeviceId(deviceId);

        if (deviceErrLog == null || !MyLists.notNullAndEmpty(deviceErrLog.getDetails())) {
            return new ArrayList<>();
        }

        return deviceErrLog.getDetails()
                .stream()
                .sorted(Comparator.comparingInt(Details::getOrder).reversed())
                .collect(Collectors.toList());
    }

    public void valueDetech(DeviceDto deviceDto) {
        ErrororUtil.isTrue(deviceDto.getSafeValueDown() == null && deviceDto.getGetSafeValueUp() == null,
                "设备新增", "安全值下限,上限必须填一项");
        ErrororUtil.isTrue(deviceDto.getSafeValueDown() != null &&
                        deviceDto.getGetSafeValueUp() != null &&
                        deviceDto.getSafeValueDown() >= deviceDto.getGetSafeValueUp(),
                "设备新增", "安全值上限需大于上限");

        ErrororUtil.isTrue(deviceDto.getEarlyAlarmValueDown() == null && deviceDto.getEarlyAlarmValueUp() == null,
                "设备新增", "预警值下限,上限必须填一项");
        ErrororUtil.isTrue(deviceDto.getEarlyAlarmValueDown() != null &&
                        deviceDto.getEarlyAlarmValueUp() != null &&
                        deviceDto.getEarlyAlarmValueDown() >= deviceDto.getEarlyAlarmValueUp(),
                "设备新增", "预警值上限需大于上限");

        ErrororUtil.isTrue(deviceDto.getSafeValueDown() != null && deviceDto.getEarlyAlarmValueDown() == null,
                "设备新增", "安全值下限和预警值下限需同时填写");
        ErrororUtil.isTrue(deviceDto.getEarlyAlarmValueDown() != null && deviceDto.getSafeValueDown() == null,
                "设备新增", "安全值下限和预警值下限需同时填写");
        ErrororUtil.isTrue(deviceDto.getGetSafeValueUp() != null && deviceDto.getEarlyAlarmValueUp() == null,
                "设备新增", "安全值上限和预警值上限需同时填写");
        ErrororUtil.isTrue(deviceDto.getEarlyAlarmValueUp() != null && deviceDto.getGetSafeValueUp() == null,
                "设备新增", "安全值上限和预警值上限需同时填写");

        ErrororUtil.isTrue(deviceDto.getSafeValueDown() != null &&
                        deviceDto.getEarlyAlarmValueDown() != null &&
                        deviceDto.getSafeValueDown() >= deviceDto.getEarlyAlarmValueDown(),
                "设备新增", "预警值下限需大于安全值下限");

        ErrororUtil.isTrue(deviceDto.getGetSafeValueUp() != null &&
                        deviceDto.getEarlyAlarmValueUp() != null &&
                        deviceDto.getGetSafeValueUp() <= deviceDto.getEarlyAlarmValueUp(),
                "设备新增", "预警值上限需小于安全值上限");
    }

    @Override
    public void updateDeviceStatus(String deviceId, Integer status) {
        Device device = deviceDao.findByIdAndDeleteAndStatus(deviceId, BaojinConstant.IS_NO_DELETE, 1);
        if (device != null) {
            Device deviceUpdate = new Device(deviceId, status, System.currentTimeMillis());
            deviceRepository.updateDeviceNotNull(deviceUpdate);
        }
    }
}
